Skip to content

feat(shaders): add simple single-pass Blur shader#40

Merged
chiefcll merged 3 commits into
mainfrom
feat/blur-shader
May 26, 2026
Merged

feat(shaders): add simple single-pass Blur shader#40
chiefcll merged 3 commits into
mainfrom
feat/blur-shader

Conversation

@chiefcll
Copy link
Copy Markdown
Contributor

Summary

  • Adds a Blur shader for both WebGL and Canvas2D backends, intended primarily for nodes with an Image Texture.
  • WebGL: single-pass 9-tap Gaussian-approximation kernel (1,2,1 / 2,4,2 / 1,2,1) / 16 — no render target, no second pass, fixed sample count for predictable cost on constrained devices.
  • Canvas2D: delegates to the native ctx.filter = 'blur(Npx)' and relies on saveAndRestore: true so the renderer cleans up filter state automatically.
  • Single amount prop (node-space pixels, default 4).

Files

  • src/core/shaders/templates/BlurTemplate.ts — props + default
  • src/core/shaders/webgl/Blur.ts — WebGL fragment shader
  • src/core/shaders/canvas/Blur.ts — Canvas2D filter-based shader
  • exports/{webgl,canvas}-shaders.ts — public re-exports
  • examples/tests/shader-blur.ts — visual regression example at amounts [0, 2, 6, 12]
  • src/core/shaders/templates/BlurTemplate.test.ts — unit tests

Tradeoffs

  • Single-pass design: large amount values (>~8) lose smoothness because there are only 9 fixed taps. For heavier blur, a separable two-pass via RenderTexture would be needed — intentionally out of scope here per "simple/performant."
  • Canvas2D blur depends on native ctx.filter (Chrome 53+). Browsers below the floor will silently no-op rather than emulate in JS.

Test plan

  • pnpm build — clean
  • pnpm test (BlurTemplate) — passing
  • pnpm test:visual:update then review snapshot for shader-blur before merging
  • Manually verify on an Image Texture node in pnpm start

🤖 Generated with Claude Code

Adds a Blur shader for both WebGL and Canvas2D backends, intended primarily
for nodes with an Image Texture. WebGL uses a 9-tap Gaussian-approximation
kernel in a single fragment pass (no render target, no second pass) to keep
it cheap on constrained devices. Canvas2D delegates to the native
`ctx.filter = 'blur(Npx)'`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@chiefcll chiefcll force-pushed the feat/blur-shader branch from eaa8c2b to 7f9447e Compare May 26, 2026 20:49
chiefcll and others added 2 commits May 26, 2026 16:52
Without registration, `renderer.createShader('Blur', ...)` falls back to
the default shader, so the shader-blur example rendered all four nodes
identically without any blur applied.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@chiefcll chiefcll merged commit 243fc30 into main May 26, 2026
1 check failed
@chiefcll chiefcll deleted the feat/blur-shader branch May 26, 2026 21:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant